package com.heisnenhub.common.module.utils;

import com.google.common.collect.Maps;
import com.heisnenhub.common.module.constant.HttpConstant;
import com.heisnenhub.common.module.enmus.ApiReturnEnums;
import com.heisnenhub.common.module.inter.ThreeResult;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

@Data
public class  Api<T>  implements ThreeResult {
    private static final long serialVersionUID = -8713837118340960775L;

    private String msg;

    /**
     * 1 是成功   0是 失败
     */
    private Integer code;

    private T data;

    @Override
    public String toString() {
        return "code=" + code + " message=" + msg + " data=" + data;
    }

    public static  Api fail() {
        return fail(HttpConstant.HttpCode.SC_FAILE,HttpConstant.HttpMsg.MSG_FAIL);
    }


    public static  Api fail(String msg) {
        return fail(HttpConstant.HttpCode.SC_FAILE,msg);
    }

    public static  Api fail(Integer code ,String msg) {
        Api ret = new Api();
        ret.setCode(code);
        ret.setMsg(msg);
        return ret;
    }





    public static Api ok() {
        Api ret = new Api();
        ret.setCode(HttpConstant.HttpCode.SC_OK);
        ret.setMsg(HttpConstant.HttpMsg.MSG_OK);
        return ret;
    }

    public static <T> Api<T> OkMessage(String message) {
        Api ret = new Api();
        ret.setCode(HttpConstant.HttpCode.SC_OK);
        ret.setMsg(message);
        return ret;
    }


    public static <T> Api<T> ok(T data) {
        Api ret = ok();
        ret.setData(data);
        return ret;
    }

    /**
     *  enum 异常
     * @param apiReturnEnums
     * @param <T>
     * @return
     */
    public static <T> Api<T> fail(ApiReturnEnums apiReturnEnums) {
         return fail(apiReturnEnums.getCode(),apiReturnEnums.getDesc());
    }

    /**
     *  解析字符串 返回
     * @param apiReturnEnums
     * @param msg
     * @param <T>
     * @return
     */
    public static <T> Api<T> failFormat(ApiReturnEnums apiReturnEnums , String ...msg) {
        Api<T> ret = fail(apiReturnEnums);
        ret.setMsg(String.format(apiReturnEnums.getDesc(),msg) );
        return ret;
    }

    /**
     *  解析字符串 返回
     * @param formatMsg
     * @param msg
     * @return
     */
    public static <T> Api<T> failFormat(String msg ,String ...formatMsg) {
        return fail(HttpConstant.HttpCode.SC_FAILE,String.format(msg,formatMsg));
    }




    public static Builder of(Integer code) {
        return of(0 < code );
    }




    public static Builder of(Boolean bool) {
        Builder builder = new Builder();
        if(bool) return builder.code(HttpConstant.HttpCode.SC_OK);
        return builder.code(HttpConstant.HttpCode.SC_FAILE);
    }

    @Data
    public static class Builder<T>{
        private String failMsg;

        private String okMsg;

        private Integer code;

        private T data;

        public Builder failMsg(String msg) {
            this.failMsg = msg;
            return this;
        }

        public Builder OkMsg(String msg) {
            this.okMsg = msg;
            return this;
        }

        private Builder code(int code) {
            this.code = code;
            return this;
        }

        public Builder data(T data) {
            this.data = data;
            return this;
        }

        public Api build() {
            Api api = new Api<T>();
            api.setCode(code);
            if(code== HttpConstant.HttpCode.SC_OK) {
                api.setMsg((HubObjectUtils.isEmpty(okMsg)? HttpConstant.HttpMsg.MSG_OK : okMsg ));
                api.setData(data);
            }else{
                api.setMsg(HubObjectUtils.isEmpty(failMsg)? HttpConstant.HttpMsg.MSG_FAIL : failMsg);
            }

            return api;
        }
    }



    /**
     * 构建返回的JSON数据格式
     *
     * @param apiReturnEnums
     * @return
     */
    public static Map<String, Object> makeJsonByEnums(ApiReturnEnums apiReturnEnums) {
        HashMap<String, Object> map = Maps.newHashMap();
        map.put("msg", apiReturnEnums.getDesc());
        map.put("code", apiReturnEnums.getCode());
        map.put("data", null);
        return map;

    }


    public  boolean isOk() {
        return this.code ==  HttpConstant.HttpCode.SC_OK;
    }


}
